
# Loading Regex library
library(qdapRegex)
Attaching package: ‘qdapRegex’
The following object is masked from ‘package:dplyr’:
explain
The following object is masked from ‘package:ggplot2’:
%+%
# Extract tweet text from climate dataset
twt_txt <- climate_twts$text
head(twt_txt)
[1] "I don't think it's too much of an exaggeration to say everyone's fate on the planet probably hinges on the dems winning these 2 Georgia Senate seats the science is clear https://t.co/qmFkKqOwC2 https://t.co/M04ZS22LB0"
[2] "BOM and CSIRO State of the Climate 2020 shows Australia is experiencing climate change now\nhttps://t.co/HdxntH6ziX"
[3] "\"[this] “offensive inquisitiveness” whose goal of humiliating others [is] inherently objectionable... “gossip derived from malicious judgment of others” could only “cast a shadow of worthlessness” over humanity + climate of rage ... inimical to civil peace and social progress.\""
[4] "Trashing Labor on Climate policy,\nHas Michelle looked at the government??\n\nApparently it’s ok to question China on everything but it’s not ok to question thing’s attacks on US democracy.\n\nhttps://t.co/Djschiqc9g"
[5] "@BigDuke6__ @djmirk @CytometerMan @DPWIMM @realDonaldTrump @ChanelRion @OANN Funny, I thought that was climate change??"
[6] "@timinmitcham Expect thousands of climate change refugees to seek asylum!"
# Remove URLs from the tweet text
twt_txt_url <- rm_twitter_url(twt_txt)
# Replace special characters, punctuation, & numbers with spaces
twt_txt_chrs <- gsub("[^A-Za-z]"," " , twt_txt_url)
# Loading text mining library
library(tm)
Loading required package: NLP
Attaching package: ‘NLP’
The following object is masked from ‘package:ggplot2’:
annotate
# Convert text in "twt_gsub" dataset to a text corpus
twt_corpus <- twt_txt_chrs %>%
VectorSource() %>%
Corpus()
# Convert the corpus to lowercase
twt_corpus_lwr <- tm_map(twt_corpus, tolower)
transformation drops documents
# Remove English stop words from the corpus using SMART dictionary and view the corpus
twt_corpus_stpwd <- tm_map(twt_corpus_lwr, removeWords, stopwords("smart"))
transformation drops documents
head(twt_corpus_stpwd$content)
[1] " don exaggeration fate planet hinges dems winning georgia senate seats science clear"
[2] "bom csiro state climate shows australia experiencing climate change "
[3] " offensive inquisitiveness goal humiliating inherently objectionable gossip derived malicious judgment cast shadow worthlessness humanity climate rage inimical civil peace social progress "
[4] "trashing labor climate policy michelle looked government apparently question china question thing attacks democracy "
[5] " bigduke djmirk cytometerman dpwimm realdonaldtrump chanelrion oann funny thought climate change "
[6] " timinmitcham expect thousands climate change refugees seek asylum "
# Remove additional spaces from the corpus
twt_corpus_spaces <- tm_map(twt_corpus_stpwd, stripWhitespace)
transformation drops documents
# Loading library for text analysis
library(qdap)
Loading required package: qdapDictionaries
Loading required package: qdapTools
Registered S3 method overwritten by 'data.table':
method from
print.data.table
Attaching package: ‘qdapTools’
The following object is masked from ‘package:dplyr’:
id
Loading required package: RColorBrewer
Attaching package: ‘qdap’
The following objects are masked from ‘package:tm’:
as.DocumentTermMatrix, as.TermDocumentMatrix
The following object is masked from ‘package:NLP’:
ngrams
The following object is masked from ‘package:rtweet’:
%>%
The following object is masked from ‘package:forcats’:
%>%
The following object is masked from ‘package:stringr’:
%>%
The following object is masked from ‘package:dplyr’:
%>%
The following object is masked from ‘package:purrr’:
%>%
The following object is masked from ‘package:tidyr’:
%>%
The following object is masked from ‘package:tibble’:
%>%
The following objects are masked from ‘package:base’:
Filter, proportions
# Extract term frequencies for top 60 words and view output
termfreq <- freq_terms(twt_corpus_spaces, 60)
termfreq
# Create a vector of custom stop words
custom_stopwds <- c("amp", "ve", "don", "lo", "climate", "change")
# Remove custom stop words and create a refined corpus
corp_refined <- tm_map(twt_corpus_spaces, removeWords, custom_stopwds)
transformation drops documents
# Extract term frequencies for the top 25 words
termfreq_25w <- freq_terms(corp_refined, 25)
# Identify terms with more than 30 counts from the top 25 list
term30 <- subset(termfreq_25w, FREQ > 30)
# Barchart
term30 %>%
ggplot() +
aes(x = reorder(WORD, -FREQ), y = FREQ) +
geom_bar(stat = "identity", fill = "blue") +
theme(axis.text.x = element_text(angle = 45, hjust = 1))

# Create word cloud with 10 colors and max 30 words
wordcloud(corp_refined, max.words = 30,
colors = brewer.pal(10, "Dark2"),
scale=c(4,1), random.order = FALSE)
n too large, allowed maximum for palette Dark2 is 8
Returning the palette you asked for with that many colors

# Load libraries
library(topicmodels)
# Create a document term matrix (DTM) for *climate*
dtm_climate <- DocumentTermMatrix(corp_refined)
# Find the sum of word counts in each document
rowTotals <- apply(dtm_climate, 1, sum)
# Select rows with a row total greater than zero
dtm_climate_new <- dtm_climate[rowTotals > 0, ]
# Create a topic model with 10 topics
topicmodl_10 <- LDA(dtm_climate_new, k = 10)
# Select and view the top 10 terms in the topic model
top_10terms <- terms(topicmodl_10, 10)
top_10terms
Topic 1 Topic 2 Topic 3 Topic 4 Topic 5 Topic 6 Topic 7
[1,] "trump" "people" "action" "global" "time" "global" "work"
[2,] "crisis" "biden" "make" "biden" "covid" "biden" "people"
[3,] "biden" "action" "global" "action" "environment" "energy" "biden"
[4,] "snow" "science" "science" "oil" "green" "years" "energy"
[5,] "action" "energy" "biden" "world" "snow" "today" "policy"
[6,] "nov" "covid" "time" "australia" "world" "emissions" "world"
[7,] "oil" "health" "live" "crisis" "great" "people" "political"
[8,] "years" "make" "crisis" "big" "planet" "crisis" "crisis"
[9,] "government" "report" "years" "report" "global" "science" "good"
[10,] "green" "years" "good" "science" "pandemic" "trump" "future"
Topic 8 Topic 9 Topic 10
[1,] "biden" "people" "people"
[2,] "trump" "world" "world"
[3,] "action" "csiro" "biden"
[4,] "covid" "global" "justice"
[5,] "future" "control" "make"
[6,] "world" "time" "crisis"
[7,] "current" "great" "current"
[8,] "year" "lost" "future"
[9,] "government" "year" "emissions"
[10,] "carbon" "state" "health"
library(syuzhet)
Attaching package: ‘syuzhet’
The following object is masked from ‘package:rtweet’:
get_tokens
# Perform sentiment analysis for tweets on `ClimateCrisis`
sa.value <- get_nrc_sentiment(climate_twts$text)
`filter_()` is deprecated as of dplyr 0.7.0.
Please use `filter()` instead.
See vignette('programming') for more help
[90mThis warning is displayed once every 8 hours.[39m
[90mCall `lifecycle::last_warnings()` to see where this warning was generated.[39m`group_by_()` is deprecated as of dplyr 0.7.0.
Please use `group_by()` instead.
See vignette('programming') for more help
[90mThis warning is displayed once every 8 hours.[39m
[90mCall `lifecycle::last_warnings()` to see where this warning was generated.[39m`data_frame()` is deprecated as of tibble 1.1.0.
Please use `tibble()` instead.
[90mThis warning is displayed once every 8 hours.[39m
[90mCall `lifecycle::last_warnings()` to see where this warning was generated.[39m
# View the sentiment scores
head(sa.value, 10)
# Calculate sum of sentiment scores
score <- colSums(sa.value[,])
# Convert the sum of scores to a data frame
score_df <- data.frame(score)
# Convert row names into 'sentiment' column and combine with sentiment scores
score_df2 <- cbind(sentiment = row.names(score_df),
score_df, row.names = NULL)
print(score_df2)
# Plot the sentiment scores
ggplot(data = score_df2, aes(x = sentiment, y = score, fill = sentiment)) +
geom_bar(stat = "identity") +
theme(axis.text.x = element_text(angle = 45, hjust = 1))

library(igraph)
# Extract source vertex and target vertex from the tweet data frame
rply_df <- climate_twts[, c("screen_name" , "reply_to_screen_name" )]
# Remove rows with missing values
rply_df_new <- rply_df[complete.cases(rply_df), ]
# Create a matrix
rply_matrx <- as.matrix(rply_df_new)
# Convert the matrix to a reply network
nw_rply <- graph_from_edgelist(el = rply_matrx, directed = TRUE)
# Calculate out-degree scores from the retweet network
out_degree <- degree(nw_rply, mode = c("out"))
# Sort the out-degree scores in decreasing order
out_degree_sort <- sort(out_degree, decreasing = TRUE)
# View users with the top 20 out-degree scores
out_degree_sort[1:20]
JimBuckley73 kgrandia erinbiba Climatehope2 CletusNwafor GuyRemorganised
44 37 16 14 14 13
NatBullard RebeccaElisabe3 NickThorsch KQ_VanCity bjames280961 eviyal
13 11 11 11 9 9
Richard09224278 _ppmv richardwakelin3 SurfTasmania verconnell BetelgeuseLxvi
8 8 8 8 8 8
climate_2017 beatulagan
7 6
# Compute the in-degree scores from the retweet network
in_degree <- degree(nw_rply, mode = c("in"))
# Sort the in-degree scores in decreasing order
in_degree_sort <- sort(in_degree, decreasing = TRUE)
# View users with the top 10 in-degree scores
in_degree_sort[1:10]
BorisJohnson senatemajldr afneil KamalaHarris seanhannity mcuban
179 74 70 63 57 51
ozm realDonaldTrump JoeBiden zerohedge
43 41 30 24
# Calculate the betweenness scores from the retweet network
Warning messages:
1: In readChar(file, size, TRUE) : truncating string with embedded nuls
2: In readChar(file, size, TRUE) : truncating string with embedded nuls
3: In readChar(file, size, TRUE) : truncating string with embedded nuls
4: In readChar(file, size, TRUE) : truncating string with embedded nuls
betwn_nw <- betweenness(nw_rply, directed = TRUE)
# Sort betweenness scores in decreasing order and round the values
betwn_nw_sort <- betwn_nw %>%
sort(decreasing = TRUE) %>%
round()
# View users with the top 10 betweenness scores
betwn_nw_sort[1:10]
XRebellionUK bjames280961 RebeccaElisabe3 richardabetts Climatehope2 erinbiba
203 184 68 39 29 21
emilyhewertson hausfath T0myBarrient0s JesseLReynolds
20 19 18 14
nw_rply
IGRAPH 520fffe DN-- 9441 7121 --
+ attr: name (v/c), followers (v/c)
+ edges from 520fffe (vertex names):
[1] jamesmiller62 ->jamesmiller62 pjstack ->BigDuke6__
[3] 5b8c196ba3654e3->5b8c196ba3654e3 JimBuckley73 ->FinanceInCommon
[5] JimBuckley73 ->SenWarren JimBuckley73 ->9NewsSyd
[7] JimBuckley73 ->senatemajldr JimBuckley73 ->senatemajldr
[9] JimBuckley73 ->GOP JimBuckley73 ->SkyNewsAust
[11] JimBuckley73 ->StateDept JimBuckley73 ->TheDemocrats
[13] JimBuckley73 ->nyunggai JimBuckley73 ->StateDept
[15] JimBuckley73 ->SkyNewsAust JimBuckley73 ->ryanwmccormack
+ ... omitted several edges
library(maps)
# Extract geo-coordinates data to append as new columns
cc_coord <- lat_lng(climate_twts)
# Omit rows with missing geo-coordinates in the data frame
cc_geo <- na.omit(cc_coord[,c("lat", "lng")])
# Plot longitude and latitude values of tweets on UK
map(database = "world", region = "UK(?!r)", fill = TRUE, col = "light green")
with(cc_geo, points(lng, lat, pch = 20, cex = 1, col = 'blue'))

# Plot longitude and latitude values of tweets on the world map
map(database = "world", fill = TRUE, col = "light green")
with(cc_geo, points(lng, lat, pch = 20, cex = 1, col = 'blue'))

LS0tCnRpdGxlOiAiUiBOb3RlYm9vayIKb3V0cHV0OiBodG1sX25vdGVib29rCi0tLQoKYGBge3IgbWVzc2FnZT1GQUxTRX0KIyBMb2FkIGxpYnJhcmllcwpsaWJyYXJ5KHRpZHl2ZXJzZSkKbGlicmFyeShodHRwdXYpCmxpYnJhcnkocnR3ZWV0KQpsaWJyYXJ5KHJlYWRyKQpsaWJyYXJ5KGhlcmUpCmxpYnJhcnkocmpzb24pCmBgYAoKYGBge3J9CgpjaW1hdGVfdHd0cyA8LSByZWFkX3R3aXR0ZXJfY3N2KGhlcmUoInJhd19kYXRhL2NsaW1hdGVfdHd0cy5jc3YiKSkKCmBgYAoKYGBge3J9CnRzX3Bsb3QoY2xpbWF0ZV90d3RzLCBieSA9ICJob3VycyIsIGNvbG9yID0gImJsdWUiKQpgYGAKCmBgYHtyfQojIExvYWRpbmcgUmVnZXggbGlicmFyeQpsaWJyYXJ5KHFkYXBSZWdleCkKCiMgRXh0cmFjdCB0d2VldCB0ZXh0IGZyb20gY2xpbWF0ZSBkYXRhc2V0CnR3dF90eHQgPC0gY2xpbWF0ZV90d3RzJHRleHQKaGVhZCh0d3RfdHh0KQoKIyBSZW1vdmUgVVJMcyBmcm9tIHRoZSB0d2VldCB0ZXh0CnR3dF90eHRfdXJsIDwtIHJtX3R3aXR0ZXJfdXJsKHR3dF90eHQpCgojIFJlcGxhY2Ugc3BlY2lhbCBjaGFyYWN0ZXJzLCBwdW5jdHVhdGlvbiwgJiBudW1iZXJzIHdpdGggc3BhY2VzCnR3dF90eHRfY2hycyAgPC0gZ3N1YigiW15BLVphLXpdIiwiICIgLCB0d3RfdHh0X3VybCkKCiMgTG9hZGluZyB0ZXh0IG1pbmluZyBsaWJyYXJ5CmxpYnJhcnkodG0pCgojIENvbnZlcnQgdGV4dCBpbiAidHd0X2dzdWIiIGRhdGFzZXQgdG8gYSB0ZXh0IGNvcnB1cwp0d3RfY29ycHVzIDwtIHR3dF90eHRfY2hycyAlPiUgCiAgICAgICAgICAgICAgICBWZWN0b3JTb3VyY2UoKSAlPiUgCiAgICAgICAgICAgICAgICBDb3JwdXMoKSAKCiMgQ29udmVydCB0aGUgY29ycHVzIHRvIGxvd2VyY2FzZQp0d3RfY29ycHVzX2x3ciA8LSB0bV9tYXAodHd0X2NvcnB1cywgdG9sb3dlcikgCgojIFJlbW92ZSBFbmdsaXNoIHN0b3Agd29yZHMgZnJvbSB0aGUgY29ycHVzIHVzaW5nIFNNQVJUIGRpY3Rpb25hcnkgYW5kIHZpZXcgdGhlIGNvcnB1cwp0d3RfY29ycHVzX3N0cHdkIDwtIHRtX21hcCh0d3RfY29ycHVzX2x3ciwgcmVtb3ZlV29yZHMsIHN0b3B3b3Jkcygic21hcnQiKSkKaGVhZCh0d3RfY29ycHVzX3N0cHdkJGNvbnRlbnQpCgojIFJlbW92ZSBhZGRpdGlvbmFsIHNwYWNlcyBmcm9tIHRoZSBjb3JwdXMKdHd0X2NvcnB1c19zcGFjZXMgPC0gdG1fbWFwKHR3dF9jb3JwdXNfc3Rwd2QsIHN0cmlwV2hpdGVzcGFjZSkKCiMgTG9hZGluZyBsaWJyYXJ5IGZvciB0ZXh0IGFuYWx5c2lzCmxpYnJhcnkocWRhcCkKCiMgRXh0cmFjdCB0ZXJtIGZyZXF1ZW5jaWVzIGZvciB0b3AgNjAgd29yZHMgYW5kIHZpZXcgb3V0cHV0CnRlcm1mcmVxICA8LSAgZnJlcV90ZXJtcyh0d3RfY29ycHVzX3NwYWNlcywgNjApCnRlcm1mcmVxCmBgYAoKYGBge3J9CiMgQ3JlYXRlIGEgdmVjdG9yIG9mIGN1c3RvbSBzdG9wIHdvcmRzCmN1c3RvbV9zdG9wd2RzIDwtIGMoImFtcCIsICJ2ZSIsICJkb24iLCAibG8iLCAiY2xpbWF0ZSIsICJjaGFuZ2UiKQoKIyBSZW1vdmUgY3VzdG9tIHN0b3Agd29yZHMgYW5kIGNyZWF0ZSBhIHJlZmluZWQgY29ycHVzCmNvcnBfcmVmaW5lZCA8LSB0bV9tYXAodHd0X2NvcnB1c19zcGFjZXMsIHJlbW92ZVdvcmRzLCBjdXN0b21fc3RvcHdkcykgCgojIEV4dHJhY3QgdGVybSBmcmVxdWVuY2llcyBmb3IgdGhlIHRvcCAyNSB3b3Jkcwp0ZXJtZnJlcV8yNXcgPC0gZnJlcV90ZXJtcyhjb3JwX3JlZmluZWQsIDI1KQoKIyBJZGVudGlmeSB0ZXJtcyB3aXRoIG1vcmUgdGhhbiAzMCBjb3VudHMgZnJvbSB0aGUgdG9wIDI1IGxpc3QKdGVybTMwIDwtIHN1YnNldCh0ZXJtZnJlcV8yNXcsIEZSRVEgPiAzMCkKCgojIEJhcmNoYXJ0CnRlcm0zMCAlPiUgCmdncGxvdCgpICsKYWVzKHggPSByZW9yZGVyKFdPUkQsIC1GUkVRKSwgeSA9IEZSRVEpICsKCQlnZW9tX2JhcihzdGF0ID0gImlkZW50aXR5IiwgZmlsbCA9ICJibHVlIikgKyAKICAgICAgICB0aGVtZShheGlzLnRleHQueCA9IGVsZW1lbnRfdGV4dChhbmdsZSA9IDQ1LCBoanVzdCA9IDEpKQpgYGAKCmBgYHtyfQpsaWJyYXJ5KFJDb2xvckJyZXdlcikKbGlicmFyeSh3b3JkY2xvdWQpCgojIENyZWF0ZSB3b3JkIGNsb3VkIHdpdGggMTAgY29sb3JzIGFuZCBtYXggMzAgd29yZHMKd29yZGNsb3VkKGNvcnBfcmVmaW5lZCwgbWF4LndvcmRzID0gMzAsIAogICAgY29sb3JzID0gYnJld2VyLnBhbCgxMCwgIkRhcmsyIiksIAogICAgc2NhbGU9Yyg0LDEpLCByYW5kb20ub3JkZXIgPSBGQUxTRSkKYGBgCgpgYGB7cn0KCiMgTG9hZCBsaWJyYXJpZXMKbGlicmFyeSh0b3BpY21vZGVscykKCgojIENyZWF0ZSBhIGRvY3VtZW50IHRlcm0gbWF0cml4IChEVE0pIGZvciAqY2xpbWF0ZSoKZHRtX2NsaW1hdGUgPC0gRG9jdW1lbnRUZXJtTWF0cml4KGNvcnBfcmVmaW5lZCkKCiMgRmluZCB0aGUgc3VtIG9mIHdvcmQgY291bnRzIGluIGVhY2ggZG9jdW1lbnQKcm93VG90YWxzIDwtIGFwcGx5KGR0bV9jbGltYXRlLCAxLCBzdW0pCgojIFNlbGVjdCByb3dzIHdpdGggYSByb3cgdG90YWwgZ3JlYXRlciB0aGFuIHplcm8KZHRtX2NsaW1hdGVfbmV3IDwtIGR0bV9jbGltYXRlW3Jvd1RvdGFscyA+IDAsIF0KCiMgQ3JlYXRlIGEgdG9waWMgbW9kZWwgd2l0aCAxMCB0b3BpY3MKdG9waWNtb2RsXzEwIDwtIExEQShkdG1fY2xpbWF0ZV9uZXcsIGsgPSAxMCkKCiMgU2VsZWN0IGFuZCB2aWV3IHRoZSB0b3AgMTAgdGVybXMgaW4gdGhlIHRvcGljIG1vZGVsCnRvcF8xMHRlcm1zIDwtIHRlcm1zKHRvcGljbW9kbF8xMCwgMTApCnRvcF8xMHRlcm1zIAoKCmBgYAoKYGBge3J9CmxpYnJhcnkoc3l1emhldCkKCiMgUGVyZm9ybSBzZW50aW1lbnQgYW5hbHlzaXMgZm9yIHR3ZWV0cyBvbiBgY2xpbWF0ZWAgCnNhLnZhbHVlIDwtIGdldF9ucmNfc2VudGltZW50KGNsaW1hdGVfdHd0cyR0ZXh0KQoKIyBWaWV3IHRoZSBzZW50aW1lbnQgc2NvcmVzCmhlYWQoc2EudmFsdWUsIDEwKQpgYGAKCmBgYHtyfQojIENhbGN1bGF0ZSBzdW0gb2Ygc2VudGltZW50IHNjb3JlcwpzY29yZSA8LSBjb2xTdW1zKHNhLnZhbHVlWyxdKQoKIyBDb252ZXJ0IHRoZSBzdW0gb2Ygc2NvcmVzIHRvIGEgZGF0YSBmcmFtZQpzY29yZV9kZiA8LSBkYXRhLmZyYW1lKHNjb3JlKQoKIyBDb252ZXJ0IHJvdyBuYW1lcyBpbnRvICdzZW50aW1lbnQnIGNvbHVtbiBhbmQgY29tYmluZSB3aXRoIHNlbnRpbWVudCBzY29yZXMKc2NvcmVfZGYyIDwtIGNiaW5kKHNlbnRpbWVudCA9IHJvdy5uYW1lcyhzY29yZV9kZiksICAKCQkJCSAgc2NvcmVfZGYsIHJvdy5uYW1lcyA9IE5VTEwpCnByaW50KHNjb3JlX2RmMikKCiMgUGxvdCB0aGUgc2VudGltZW50IHNjb3JlcwpnZ3Bsb3QoZGF0YSA9IHNjb3JlX2RmMiwgYWVzKHggPSBzZW50aW1lbnQsIHkgPSBzY29yZSwgZmlsbCA9IHNlbnRpbWVudCkpICsKICAJIGdlb21fYmFyKHN0YXQgPSAiaWRlbnRpdHkiKSArCiAgICAgICB0aGVtZShheGlzLnRleHQueCA9IGVsZW1lbnRfdGV4dChhbmdsZSA9IDQ1LCBoanVzdCA9IDEpKQpgYGAKCmBgYHtyIG1lc3NhZ2U9RkFMU0V9CmxpYnJhcnkoaWdyYXBoKQoKIyBFeHRyYWN0IHNvdXJjZSB2ZXJ0ZXggYW5kIHRhcmdldCB2ZXJ0ZXggZnJvbSB0aGUgdHdlZXQgZGF0YSBmcmFtZQpycGx5X2RmIDwtIGNsaW1hdGVfdHd0c1ssIGMoInNjcmVlbl9uYW1lIiAsICJyZXBseV90b19zY3JlZW5fbmFtZSIgKV0KCiMgUmVtb3ZlIHJvd3Mgd2l0aCBtaXNzaW5nIHZhbHVlcwpycGx5X2RmX25ldyA8LSBycGx5X2RmW2NvbXBsZXRlLmNhc2VzKHJwbHlfZGYpLCBdCgojIENyZWF0ZSBhIG1hdHJpeApycGx5X21hdHJ4IDwtIGFzLm1hdHJpeChycGx5X2RmX25ldykKCiMgQ29udmVydCB0aGUgbWF0cml4IHRvIGEgcmVwbHkgbmV0d29yawpud19ycGx5IDwtIGdyYXBoX2Zyb21fZWRnZWxpc3QoZWwgPSBycGx5X21hdHJ4LCBkaXJlY3RlZCA9IFRSVUUpCgojIENhbGN1bGF0ZSBvdXQtZGVncmVlIHNjb3JlcyBmcm9tIHRoZSByZXR3ZWV0IG5ldHdvcmsKb3V0X2RlZ3JlZSA8LSBkZWdyZWUobndfcnBseSwgbW9kZSA9IGMoIm91dCIpKQoKIyBTb3J0IHRoZSBvdXQtZGVncmVlIHNjb3JlcyBpbiBkZWNyZWFzaW5nIG9yZGVyCm91dF9kZWdyZWVfc29ydCA8LSBzb3J0KG91dF9kZWdyZWUsIGRlY3JlYXNpbmcgPSBUUlVFKQoKIyBWaWV3IHVzZXJzIHdpdGggdGhlIHRvcCAyMCBvdXQtZGVncmVlIHNjb3JlcwpvdXRfZGVncmVlX3NvcnRbMToyMF0KYGBgCgpgYGB7cn0KIyBDb21wdXRlIHRoZSBpbi1kZWdyZWUgc2NvcmVzIGZyb20gdGhlIHJldHdlZXQgbmV0d29yawppbl9kZWdyZWUgPC0gZGVncmVlKG53X3JwbHksIG1vZGUgPSBjKCJpbiIpKQoKIyBTb3J0IHRoZSBpbi1kZWdyZWUgc2NvcmVzIGluIGRlY3JlYXNpbmcgb3JkZXIKaW5fZGVncmVlX3NvcnQgPC0gc29ydChpbl9kZWdyZWUsIGRlY3JlYXNpbmcgPSBUUlVFKQoKIyBWaWV3IHVzZXJzIHdpdGggdGhlIHRvcCAxMCBpbi1kZWdyZWUgc2NvcmVzCmluX2RlZ3JlZV9zb3J0WzE6MTBdCmBgYAoKYGBge3J9CiMgQ2FsY3VsYXRlIHRoZSBiZXR3ZWVubmVzcyBzY29yZXMgZnJvbSB0aGUgcmV0d2VldCBuZXR3b3JrCmJldHduX253IDwtIGJldHdlZW5uZXNzKG53X3JwbHksIGRpcmVjdGVkID0gVFJVRSkKCiMgU29ydCBiZXR3ZWVubmVzcyBzY29yZXMgaW4gZGVjcmVhc2luZyBvcmRlciBhbmQgcm91bmQgdGhlIHZhbHVlcwpiZXR3bl9ud19zb3J0IDwtIGJldHduX253ICU+JQogICAgICAgICAgICAgICAgICAgIHNvcnQoZGVjcmVhc2luZyA9IFRSVUUpICU+JQogICAgICAgICAgICAgICAgICAgIHJvdW5kKCkKCiMgVmlldyB1c2VycyB3aXRoIHRoZSB0b3AgMTAgYmV0d2Vlbm5lc3Mgc2NvcmVzIApiZXR3bl9ud19zb3J0WzE6MTBdCmBgYAoKYGBge3J9CiMgQ3JlYXRlIGEgdmFyaWFibGUgZm9yIG91dC1kZWdyZWUKZGVnX291dCA8LSBkZWdyZWUobndfcnBseSwgbW9kZSA9IGMoIm91dCIpKQpkZWdfb3V0CgojIEFtcGxpZnkgdGhlIG91dC1kZWdyZWUgdmFsdWVzCnZlcnRfc2l6ZSA8LSAoZGVnX291dCAqIDMpCiMgKyA1CgojdXNlcnMKdXNlcl9jb3MgPC0gdXNlcnNfZGF0YShjbGltYXRlX3R3dHMpCgoKIyBDcmVhdGUgYSBjb2x1bW4gYW5kIGNhdGVnb3JpemUgZm9sbG93ZXIgY291bnRzIGFib3ZlIGFuZCBiZWxvdyA1MDAKdXNlcl9jb3MkZm9sbG93IDwtIGlmZWxzZSh1c2VyX2NvcyRmb2xsb3dlcnNfY291bnQgPiA1MDAsICIxIiwgIjAiKQoKIyBBc3NpZ24gdGhlIG5ldyBjb2x1bW4gYXMgdmVydGV4IGF0dHJpYnV0ZSB0byB0aGUgcmV0d2VldCBuZXR3b3JrClYobndfcnBseSkkZm9sbG93ZXJzIDwtIHVzZXJfY29zJGZvbGxvdwp2ZXJ0ZXhfYXR0cihud19ycGx5KQoKIyBTZXQgdGhlIHZlcnRleCBjb2xvcnMgYmFzZWQgb24gZm9sbG93ZXIgY291bnQgYW5kIGNyZWF0ZSBhIHBsb3QKc3ViX2NvbG9yIDwtIGMoImxpZ2h0Z3JlZW4iLCAidG9tYXRvIikKCnBsb3QobndfcnBseSwgYXNwID0gOS8xMiwKICAgICB2ZXJ0ZXguc2l6ZSA9IGRlZ19vdXQsIGVkZ2UuYXJyb3cuc2l6ZSA9IDAuNSwKICAgICB2ZXJ0ZXgubGFiZWwuY2V4ID0gMC44LAogICAgIHZlcnRleC5jb2xvciA9IHN1Yl9jb2xvclthcy5mYWN0b3IodmVydGV4X2F0dHIobndfcnBseSwgImZvbGxvd2VycyIpKV0sCiAgICAgdmVydGV4LmxhYmVsLmNvbG9yID0gImJsYWNrIiwgdmVydGV4LmZyYW1lLmNvbG9yID0gImdyZXkiKQpgYGAKCmBgYHtyfQoKbGlicmFyeShtYXBzKQoKIyBFeHRyYWN0IGdlby1jb29yZGluYXRlcyBkYXRhIHRvIGFwcGVuZCBhcyBuZXcgY29sdW1ucwpjY19jb29yZCA8LSBsYXRfbG5nKGNsaW1hdGVfdHd0cykKCiMgT21pdCByb3dzIHdpdGggbWlzc2luZyBnZW8tY29vcmRpbmF0ZXMgaW4gdGhlIGRhdGEgZnJhbWUKY2NfZ2VvIDwtIG5hLm9taXQoY2NfY29vcmRbLGMoImxhdCIsICJsbmciKV0pCgojIFBsb3QgbG9uZ2l0dWRlIGFuZCBsYXRpdHVkZSB2YWx1ZXMgb2YgdHdlZXRzIG9uIFVLIG1hcAptYXAoZGF0YWJhc2UgPSAid29ybGQiLCByZWdpb24gPSAiVUsoPyFyKSIsIGZpbGwgPSBUUlVFLCBjb2wgPSAibGlnaHQgZ3JlZW4iKQp3aXRoKGNjX2dlbywgcG9pbnRzKGxuZywgbGF0LCBwY2ggPSAyMCwgY2V4ID0gMSwgY29sID0gJ2JsdWUnKSkKCiMgUGxvdCBsb25naXR1ZGUgYW5kIGxhdGl0dWRlIHZhbHVlcyBvZiB0d2VldHMgb24gdGhlIHdvcmxkIG1hcAptYXAoZGF0YWJhc2UgPSAid29ybGQiLCBmaWxsID0gVFJVRSwgY29sID0gImxpZ2h0IGdyZWVuIikKd2l0aChjY19nZW8sIHBvaW50cyhsbmcsIGxhdCwgcGNoID0gMjAsIGNleCA9IDEsIGNvbCA9ICdibHVlJykpCmBgYAoK